package xdu.lz.netty.d_nio_selector.selector;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.time.LocalTime;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author lizhen
 * @date 2019/8/14 19:43
 * @desc  客户端
 */
public class NioClient {
    public static void main(String[] args)  throws Exception{

        //1获取客户端 socketchannel对象，设置非阻塞
        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.configureBlocking(false);

        //2获取选择器，并把channel的连接事件注册到selector上
        Selector selector = Selector.open();
        socketChannel.register(selector,SelectionKey.OP_CONNECT);
        //3连接服务器
        socketChannel.connect(new InetSocketAddress(8899));

        //
        while (true){

            selector.select(); //阻塞等待事件
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            selectionKeys.forEach(selectionKey -> {
                //4与服务器建立连接会回调
                if (selectionKey.isConnectable()) {
                    SocketChannel client = (SocketChannel) selectionKey.channel();
                    //Tells whether or not a connection operation is in progress on this channel.
                    if (client.isConnectionPending()) {
                        //Finishes the process of connecting a socket channel.
                        try {
                            client.finishConnect();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        //5此时连接已经建立成功
                        ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
                        writeBuffer.put((LocalTime.now()+"连接成功").getBytes());
                        writeBuffer.flip();
                        try {
                            client.write(writeBuffer);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                        /**
                         * 6 此时客户端获得键盘输入流来发送给服务器
                         *   由于键盘输入是阻塞的，所以要开启一个线程
                         */
                        //通过线程池建立单线程
                        ExecutorService executorService = Executors.newSingleThreadExecutor(Executors.defaultThreadFactory());
                        executorService.submit(() -> {
                            while(true){

                                writeBuffer.clear();
                                InputStreamReader inputStreamReader = new InputStreamReader(System.in);
                                BufferedReader br = new BufferedReader(inputStreamReader);

                                String writeMsg = br.readLine();
                                writeBuffer.put(writeMsg.getBytes());
                                writeBuffer.flip();
                                client.write(writeBuffer);
                            }

                        });

                    }
                    //7注册读取事件
                    try {
                        client.register(selector,SelectionKey.OP_READ);
                    } catch (ClosedChannelException e) {
                        e.printStackTrace();
                    }

                }else if(selectionKey.isReadable()){
                    SocketChannel client = (SocketChannel) selectionKey.channel();
                    ByteBuffer readBuffer = ByteBuffer.allocate(1024);
                    int read = 0;
                    try {
                        read = client.read(readBuffer);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    if ( read > 0 ) {
                        String receiveMsg = new String(readBuffer.array(), 0, read);
                        System.out.println(receiveMsg);
                    }
                }
            });

            //8清除selectionKey
            selectionKeys.clear();
        }
    }
}
